﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;

namespace Mandarine.Util
{
    /// <summary>
    /// 文字列ユーティリティヘルパ拡張メソッドを提供します
    /// 
    /// </summary>
    /// <date>9/15, 2011 </date>
    ///
    public static class StrUtil
    {
        /// <summary>
        /// 値が空かどうかを判定します
        /// </summary>
        /// <param name="val">値をセット</param>
        /// <returns>bool 値が空ならばtrueが戻ります</returns>
        public static bool IsEmpty(this string val)
        {
            return string.IsNullOrEmpty(val);
        }
        /// <summary>
        /// 値が空ではないかを判定します
        /// </summary>
        /// <param name="val">値をセット</param>
        /// <returns>bool 値が空ではなければtrueが戻ります</returns>
        public static bool IsNotEmpty(this string val)
        {
            return ! (IsEmpty(val));
        }
        /// <summary>
        /// 値が全て空かどうかを判定します
        /// </summary>
        /// <param name="vals">値をセット</param>
        /// <returns>bool 値が空ならばtrueが戻ります</returns>
        public static bool IsEmpty(params string[] vals)
        {
            return (vals == null || vals.Length == 0) ? true: false;
        }
        /// <summary>
        /// 値が全て空ではないかを判定します
        /// </summary>
        /// <param name="vals">値をセット</param>
        /// <returns>bool 値が空ならばtrueが戻ります</returns>
        public static bool IsNotEmpty(params string[] vals)
        {
            return !(IsEmpty(vals));
        }
        /// <summary>
        /// 値が空かどうかを判定します
        /// </summary>
        /// <param name="val">値をセット</param>
        /// <returns>bool 値が空ならばtrueが戻ります</returns>
        public static bool IsEmpty(this ICollection val)
        {
            return (val == null || val.Count == 0) ? true : false;
        }
        /// <summary>
        /// 値が空ではないかを判定します
        /// </summary>
        /// <param name="val">値をセット</param>
        /// <returns>bool 値が空ではなければtrueが戻ります</returns>
        public static bool IsNotEmpty(this ICollection val)
        {
            return ! (IsEmpty(val));
        }
        /// <summary>
        /// 値が空ではないかを判定します
        /// </summary>
        /// <param name="val">値をセット</param>
        /// <returns>bool 値が空ではなければtrueが戻ります</returns>
        public static bool IsEmpty(this ICollection<object> val)
        {
            return (val == null || val.Count == 0) ? true : false;
        }

        /// <summary>
        /// 対象の文字列がUnicode漢字かどうかを検査します
        /// </summary>
        /// <param name="target">対象文字列をセット</param>
        /// <returns>文字列がUnicode漢字であればtrueが戻ります</returns>
        public static bool IsKanji(this string target)
        {
            return Regex.IsMatch(target, @"^\p{IsCJKUnifiedIdeographs}*$");
        }
        /// <summary>
        /// 対象の文字列がUnicodeひらかなかどうかを検査します
        /// </summary>
        /// <param name="target">対象文字列をセット</param>
        /// <returns>文字列がUnicodeひらかなであればtrueが戻ります</returns>
        public static bool IsHirakana(this string target)
        {
            return Regex.IsMatch(target, @"^\p{IsHiragana}*$");
        }
        /// <summary>
        /// 対象の文字列がUnicodeカタカナかどうかを検査します
        /// </summary>
        /// <param name="target">対象文字列をセット</param>
        /// <returns>文字列がUnicodeカタカナであればtrueが戻ります</returns>
        public static bool IsKatakana(this string target)
        {
            return Regex.IsMatch(target, @"^\p{IsKatakana}*$");
        }
        /// <summary>
        /// 先頭を小文字に変換した文字列を取得します(デキャピタライズ)
        /// </summary>
        /// <param name="name">対象の文字をセット</param>
        /// <returns>先頭が小文字に変換された文字列が戻ります</returns>
        public static string Decapitalize(this string name)
        {
            if (IsEmpty(name)) {
                return name;
            }
            char[] chars = name.ToCharArray();
            chars[0] = Char.ToLower(chars[0]);
            return new string(chars);
        }
        /// <summary>
        /// 先頭を大文字に変換した文字列を取得します(キャピタライズ)
        /// </summary>
        /// <param name="name">対象の文字をセット</param>
        /// <returns>先頭が大文字に変換された文字列が戻ります</returns>
        public static string Capitalize(this string name)
        {
            if (IsEmpty(name)) {
                return name;
            }
            char[] chars = name.ToCharArray();
            chars[0] = Char.ToUpper(chars[0]);
            return new string(chars);
        }
        /// <summary>
        /// 文字列のケースを変換します
        /// </summary>
        /// <param name="phrase">対象のフレーズをセット</param>
        /// <param name="cases">変換するケースをセット</param>
        /// <returns>string</returns>
        static string ConvertCaseString(this string phrase, Case cases)
        {
            string[] splittedPhrase = phrase.Split(' ', '-', '.');
            var sb = new StringBuilder();

            if (cases == Case.CamelCase)
            {
                sb.Append(splittedPhrase[0].ToLower());
                splittedPhrase[0] = string.Empty;
            }
            else if (cases == Case.PascalCase)
                sb = new StringBuilder();

            foreach (String s in splittedPhrase)
            {
                char[] splittedPhraseChars = s.ToCharArray();
                if (splittedPhraseChars.Length > 0)
                {
                    splittedPhraseChars[0] = ((new String(splittedPhraseChars[0], 1)).ToUpper().ToCharArray())[0];
                }
                sb.Append(new String(splittedPhraseChars));
            }
            return sb.ToString();
        }
        /// <summary>
        /// 文字ケースの列挙を定義します
        /// </summary>
        enum Case
        {
            PascalCase, //パスカルケース (Upper CamelCase)
            CamelCase   //キャメルケース (Lower CamelCase)
        }
    }
}
